/*
* Copyright (C) 2024-2025 Uniontech Technology Co., Ltd.
*
* Author:      zhangbingyi <zhangbingyia@uniontech.com>
*
* Maintainer:  zhangbingyi <zhangbingyia@uniontech.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "tptabledelegate.h"
#include "trustedprotectiondefinition.h"

#include <QComboBox>
//#include <DFontSizeManager>
#include <QFrame>

#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
#include <QFocusEvent>
#include <QHBoxLayout>
#include <QToolTip>

#define CHECKBOX_SIZE 20
#define COLUMN_LEFT_SPACE_1 30
#define COLUMN_RIGHT_SPACE_1 50


TPTableDelegate::TPTableDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
    , m_isViewDisabled(false)
{
    m_comboxStatusMap.insert(COMBO_PROHIBIT, CustomPolicyDeny);
    m_comboxStatusMap.insert(COMBO_WARNING, CustomPolicyWarn);
    //m_comboxStatusMap.insert(COMBO_ALLOW, CustomPolicyAllow);
}

void TPTableDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem itemOption(option);

    // 第0列上增加checkbox
    if (OBJECT_COLUMN == index.column()) {
        painter->save();

        bool isChecked = index.model()->data(index, CHECKED_STATUS_ROLE).toBool();
        int policyType = index.model()->data(index, POLICY_TYPE_ROLE).toInt();
        QStyleOptionButton checkBox;

        if (m_isViewDisabled) {
            checkBox.palette.setCurrentColorGroup(QPalette::ColorGroup::Disabled);
        }

        checkBox.state = QStyle::State_None;
        checkBox.state |= QStyle::State_Off;
        if (policyType == POLICY_DEFAULT) {
            checkBox.state |= QStyle::State_ReadOnly;
            checkBox.palette.setCurrentColorGroup(QPalette::ColorGroup::Disabled);
        } else {
            checkBox.state |= QStyle::State_Enabled;
            if (isChecked) {
                checkBox.state |= QStyle::State_On;
            }
        }

        QRect tmp = itemOption.rect;
        tmp.setX(tmp.x() + 10);
        tmp.setY(tmp.y() + 14);
        tmp.setWidth(CHECKBOX_SIZE);
        tmp.setHeight(CHECKBOX_SIZE);
        checkBox.rect = tmp;
        QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBox, painter);
        painter->restore();

        itemOption.rect = option.rect.adjusted(30, 0, 0, 0);
    }

    // 去掉焦点
    if (itemOption.state & QStyle::State_HasFocus) {
        itemOption.state = itemOption.state ^ QStyle::State_HasFocus;
    }

    QStyledItemDelegate::paint(painter, itemOption, index);
}

bool TPTableDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    if (!m_isViewDisabled) {
        QMouseEvent *mouse = static_cast<QMouseEvent *>(event);
        if (event->type() == QEvent::MouseButtonPress && option.rect.contains(mouse->pos())) {
            if (index.column() == OBJECT_COLUMN) {
                // 对于自定义对象，处理勾选事件
                if (model->data(index, POLICY_TYPE_ROLE).toInt() == POLICY_CUSTOM) {
                    bool checkeState = model->data(index, CHECKED_STATUS_ROLE).toBool();
                    model->setData(index, !checkeState, CHECKED_STATUS_ROLE);
                }
            }
        }
    }

    return QStyledItemDelegate::editorEvent(event, model, option, index);
}

QWidget *TPTableDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(option);
    if (index.column() == POLICY_COLUMN) {
        QComboBox *box = new QComboBox(parent);
        box->setFocusPolicy(Qt::FocusPolicy::NoFocus);
        // 非自定义策略禁止修改
        if (index.data(POLICY_TYPE_ROLE).toInt() != POLICY_CUSTOM) {
            box->setDisabled(true);
        }

        box->addItem(tr("Prohibit"), COMBO_PROHIBIT);
        box->addItem(tr("Warning"), COMBO_WARNING);
        //box->addItem(tr("Allow"), COMBO_ALLOW);
        int tmpIndex = COMBO_PROHIBIT;
        if (index.data(POLICY_TYPE_ROLE).toInt() == POLICY_CUSTOM) {
            int status = index.data(CUSTOM_POLICY_TYPE_ROLE).toInt();
            tmpIndex = m_comboxStatusMap.key(status, COMBO_PROHIBIT);
        }

        box->setCurrentIndex(tmpIndex);

        connect(box, SIGNAL(currentIndexChanged(int)), this, SLOT(commitEditorData()));

        box->setDisabled(m_isViewDisabled);
        return box;
    }

    return nullptr;
}

void TPTableDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    if (index.column() == POLICY_COLUMN) {
        //DComboBox *box = editor->findChild<DComboBox *>();
        if (index.data(POLICY_TYPE_ROLE).toInt() != POLICY_CUSTOM) {
            return;
        }

        QComboBox *box = static_cast<QComboBox *>(editor);
        int status = index.data(CUSTOM_POLICY_TYPE_ROLE).toInt();
        int tmpIndex;
        tmpIndex = m_comboxStatusMap.key(status, COMBO_PROHIBIT);
        box->setCurrentIndex(tmpIndex);
    }
}

void TPTableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    if (index.column() == POLICY_COLUMN) {
        QComboBox *box = static_cast<QComboBox *>(editor);
        int policyType = m_comboxStatusMap.value(box->currentIndex());

        model->setData(index, policyType, CUSTOM_POLICY_TYPE_ROLE);
        return;
    }
    QStyledItemDelegate::setModelData(editor, model, index);
}

// 修正下拉框位置
void TPTableDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem tmp(option);
    if (index.column() == POLICY_COLUMN) {
        tmp.rect.adjust(8, 5, 0, 0);
        tmp.rect.setHeight(38);
        QStyledItemDelegate::updateEditorGeometry(editor, tmp, index);
        return;
    }
    QStyledItemDelegate::updateEditorGeometry(editor, option, index);
}

void TPTableDelegate::syncDisableStatus(bool status)
{
    m_isViewDisabled = status;
}

// 针对UI设计师提出的体验性问题修改
// 1 对象与路径列，仅在文本产生省略时提供悬浮框
// 2 对象与路径列，鼠标移动到其它无悬浮效果地方时，已有的悬浮框马上消失
bool TPTableDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    if (event->type() == QEvent::ToolTip) {
        // 针对前两列
        if (index.column() == PATH_COLUMN || index.column() == OBJECT_COLUMN) {
            // 发生省略时设置并显示tooltip
            int fixedWidth = index.column() == PATH_COLUMN ? -27 : 26;
            QString tooltip = index.data(Qt::DisplayRole).toString();
            if (option.fontMetrics.width(tooltip) > option.rect.width() - fixedWidth) {
                QToolTip::showText(event->globalPos(), tooltip);
                return true;
            } else {
                QWidgetList qwl = QApplication::topLevelWidgets();
                for (QWidget *qw : qwl) {
                    if (QString("QTipLabel") == qw->metaObject()->className()) {
                        qw->close();
                    }
                }
            }
        }
    }

    return QStyledItemDelegate::helpEvent(event, view, option, index);
}

// 下拉内容变化时提交数据
void TPTableDelegate::commitEditorData()
{
    QComboBox *box = qobject_cast<QComboBox *>(sender());
    Q_EMIT commitData(box);
}
